package mirkofrancuski.battleship.game;

import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;

import mirkofrancuski.battleship.db.BoardTable;
import mirkofrancuski.battleship.db.CoordinateTable;
import mirkofrancuski.battleship.db.IntTable;

import android.R.integer;
import android.database.sqlite.SQLiteDatabase;

public class ComputerNormal extends ComputerEasy {

	protected enum Sides {
		SOUTH {
			@Override
			Coordinates calc(Coordinates coord) {
				return new Coordinates(coord.horizontal + 1, coord.vertical);
			}
		},
		NORTH {
			@Override
			Coordinates calc(Coordinates coord) {
				return new Coordinates(coord.horizontal - 1, coord.vertical);
			}
		},
		EAST {
			@Override
			Coordinates calc(Coordinates coord) {
				return new Coordinates(coord.horizontal, coord.vertical + 1);
			}
		},
		WEST {
			@Override
			Coordinates calc(Coordinates coord) {
				return new Coordinates(coord.horizontal, coord.vertical - 1);
			}
		};

		abstract Coordinates calc(Coordinates coord);
	}

	protected enum State {
		SEARCHING, DESTROY
	}

	protected State state;

	protected LinkedList<Coordinates> stack;

	protected boolean chekersSelect;

	public ComputerNormal() {
		super();
		stack = new LinkedList<Coordinates>();
		state = State.SEARCHING;
		chekersSelect = randomGenerator.nextBoolean();
	}

	@Override
	public Coordinates getShotCoordinates() {
		boolean shotSelected = false;

		while (!shotSelected) {
			if (state == State.SEARCHING) {
				lastShot = new Coordinates();
				while (true) {
					lastShot.horizontal = randomGenerator
							.nextInt(Board.BOARD_SIZE);
					lastShot.vertical = randomGenerator
							.nextInt(Board.BOARD_SIZE);

					if (!isChekers(lastShot.horizontal, lastShot.vertical))
						continue;

					if (enemyBoard.isEmpty(lastShot))
						break;
				}
				shotSelected = true;
			} else {
				try {
					lastShot = stack.pop();
					while (!enemyBoard.isEmpty(lastShot)) {
						lastShot = stack.pop();
					}
					shotSelected = true;
				} catch (Exception e) {
					state = State.SEARCHING;
					continue;					
				}
			}
		}
		noOfShots++;
		return lastShot;
	}

	protected boolean isChekers(int x, int y) {
		return chekersSelect ? (x + y) % 2 != 0 : (x + y) % 2 == 0;
	}

	@Override
	public void resultFromLastShot(Cell cell) {
		enemyBoard.updateResult(lastShot, cell);
		if (cell != Cell.MISS) {
			if (state == State.SEARCHING)
				state = State.DESTROY;

			pushAllSidesToStack();

		} else if (stack.isEmpty())
			state = State.SEARCHING;

	}
	
	@Override
	public void resultFromLastShot(Ship ship) {
		enemyBoard.updateResult(ship);
		pushAllSidesToStack();
	}

	protected void pushAllSidesToStack() {
		if (enemyBoard.isEmpty(Sides.NORTH.calc(lastShot)))
			stack.push(Sides.NORTH.calc(lastShot));
		if (enemyBoard.isEmpty(Sides.SOUTH.calc(lastShot)))
			stack.push(Sides.SOUTH.calc(lastShot));
		if (enemyBoard.isEmpty(Sides.EAST.calc(lastShot)))
			stack.push(Sides.EAST.calc(lastShot));
		if (enemyBoard.isEmpty(Sides.WEST.calc(lastShot)))
			stack.push(Sides.WEST.calc(lastShot));
	}

	@Override
	public void save(SQLiteDatabase db) {
		super.save(db);
		
		String className = ComputerNormal.class.toString();
		
		IntTable.addInt(db, className, "state", state.ordinal());
		IntTable.addInt(db, className, "chekersSelect", chekersSelect ? 1 : 0);
		
		HashMap<String,Coordinates> coordinatesHashMap = new HashMap<String, Coordinates>();
		int size = stack.size();
		IntTable.addInt(db, className, "stackSize", size);
		for(int i=0; i<size; i++){
			coordinatesHashMap.put("stack"+i, stack.pop());
		}
		CoordinateTable.addCoordinates(db, className, coordinatesHashMap);		
		
	}

	@Override
	public void restore(SQLiteDatabase db) {
		
		String className = ComputerNormal.class.toString();
		
		enemyBoard = BoardTable.restoreBoard(db, BoardTable.BOARD_GAME_COMPUTER_MAIN);
		myBoard = BoardTable.restoreBoard(db, BoardTable.BOARD_GAME_COMPUTER_SECUNDARY);
		
		HashMap<String, Integer> hashMap = IntTable.getInts(db, className);
		noOfShots = hashMap.get("noOfShots");
		
		int stateOrdinal = hashMap.get("state");
		state = State.values()[stateOrdinal];
		
		int chekersSelectInt = hashMap.get("chekersSelect");
		chekersSelect = chekersSelectInt == 1;
		
		HashMap<String, Coordinates> coordinatesHashMap = CoordinateTable.getCoordinates(db, className);
		lastShot = coordinatesHashMap.get("lastShot");
		
		stack.clear();
		int stackSize = hashMap.get("stackSize");
		for(int i=stackSize-1; i>=0; i--){
			Coordinates coord = coordinatesHashMap.get("stack" + i);
			stack.push(coord);
		}			
	}
	
	

}
